package org.jeecg.modules.file.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.file.entity.ProcurementFile;
import org.jeecg.modules.file.mapper.ProcurementFileMapper;
import org.jeecg.modules.file.service.IProcurementFileService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class ProcurementFileServiceImpl extends ServiceImpl<ProcurementFileMapper, ProcurementFile> implements IProcurementFileService {

    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    public List<ProcurementFile> queryPageList(ProcurementFile procurementFile, Integer pageNo, Integer pageSize) {
        Page<ProcurementFile> page = new Page<>(pageNo, pageSize);
        QueryWrapper<ProcurementFile> queryWrapper = new QueryWrapper<>(procurementFile);
        IPage<ProcurementFile> pageList = baseMapper.selectPage(page, queryWrapper);
        return pageList.getRecords();
    }

    @Transactional(rollbackFor = Exception.class)
    public ProcurementFile uploadFile(MultipartFile file, String bizId, String bizType) throws IOException {
        // 创建业务目录
        String bizPath = uploadpath + File.separator + "procurement" + File.separator + bizType + File.separator + bizId + File.separator;
        File saveDir = new File(bizPath);
        if (!saveDir.exists()) {
            saveDir.mkdirs();
        }

        // 保存文件
        String fileName = file.getOriginalFilename();
        String savePath = bizPath + fileName;
        File saveFile = new File(savePath);
        FileCopyUtils.copy(file.getBytes(), saveFile);

        // 构建文件记录
        ProcurementFile procurementFile = new ProcurementFile();
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (loginUser != null) {
            procurementFile.setUploadBy(loginUser.getUsername());//loginUser.getUsername()
        }
        procurementFile.setFileName(fileName);
        procurementFile.setFilePath(savePath.replace("\\", "/"));
        procurementFile.setFileSize(BigDecimal.valueOf(file.getSize()));
        procurementFile.setUploadTime(new Date());
        procurementFile.setBizId(bizId);
        procurementFile.setBizType(bizType);
        procurementFile.setCreateTime(new Date());
        procurementFile.setUpdateTime(new Date());

        // 保存记录
        baseMapper.insert(procurementFile);
        return procurementFile;
    }

    @Transactional(rollbackFor = Exception.class)
    public List<ProcurementFile> uploadFiles(MultipartFile[] files, String bizId, String bizType) throws IOException {
        List<ProcurementFile> resultList = new ArrayList<>();

        // 遍历上传每个文件
        for (MultipartFile file : files) {
            if (!file.isEmpty()) {
                ProcurementFile procurementFile = uploadFile(file, bizId, bizType);
                resultList.add(procurementFile);
            }
        }

        return resultList;
    }


    public List<ProcurementFile> getFilesByBiz(String bizId, String bizType) {
        QueryWrapper<ProcurementFile> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("biz_id", bizId);
        queryWrapper.eq("biz_type", bizType);
        return baseMapper.selectList(queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean deleteFile(String id) {
        // 查询文件信息
        ProcurementFile file = baseMapper.selectById(id);
        if (file == null) {
            return false;
        }

        // 删除文件
        File deleteFile = new File(file.getFilePath());
        if (deleteFile.exists()) {
            deleteFile.delete();
        }

        // 删除记录
        baseMapper.deleteById(id);
        return true;
    }

    @Override
    public void downloadFile(String id, HttpServletResponse response) throws Exception {
        // 根据ID查询文件信息
        ProcurementFile file = baseMapper.selectById(id);
        if (file == null) {
            throw new Exception("文件不存在");
        }

        File downloadFile = new File(file.getFilePath());
        if (!downloadFile.exists()) {
            throw new Exception("文件不存在");
        }

        // 设置响应头
        response.setContentType("application/octet-stream");
        // 处理中文文件名
        String fileName = URLEncoder.encode(file.getFileName(), "UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        response.setContentLengthLong(downloadFile.length());

        // 读取文件并写入响应流
        try (InputStream inputStream = new FileInputStream(downloadFile);
             OutputStream outputStream = response.getOutputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.flush();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ProcurementFile> uploadExcel(MultipartFile file, String bizId, String bizType) throws IOException {
        // 检查文件是否为空
        if (file == null || file.isEmpty()) {
            throw new IOException("上传文件为空");
        }

        // 检查文件类型是否为Excel
        String fileName = file.getOriginalFilename();
        if (fileName == null || (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx"))) {
            throw new IOException("请上传Excel文件");
        }

        // 使用现有的uploadFile方法上传Excel文件
        ProcurementFile procurementFile = uploadFile(file, bizId, bizType);
        List<ProcurementFile> resultList = new ArrayList<>();
        resultList.add(procurementFile);
        return resultList;
    }

}
